package com.naza.rpc.circuitBreaker;

/**
 * 
 * 熔断指标，记录每一次操作
 *
 * @author yl
 */
class CircuitBreakerMetrics implements CircuitBreaker.Metrics {

    private final RingBitSet ringBitSet;

    /**
     * Maximum number of buffered calls
     */
    private int maxNumberOfBufferedCalls;

    CircuitBreakerMetrics(int ringBufferSize) {
        this.ringBitSet = new RingBitSet(ringBufferSize);
        this.maxNumberOfBufferedCalls = ringBufferSize;
    }

    /**
     * 记录一次失败调用
     * Records a failed call and returns the current failure rate in percentage.
     *
     * @return the current failure rate  in percentage.
     */
    public synchronized float recordFailure(){
        ringBitSet.setNextBit(true);
        return getFailureRate();
    }

    /**
     * 记录一次成功调用
     * Records a successful call and returns the current failure rate in percentage.
     *
     * @return the current failure rate in percentage.
     */
    public synchronized float recordSuccess(){
        ringBitSet.setNextBit(false);
        return getFailureRate();
    }


    @Override
    public synchronized float getFailureRate(){
        int numOfMeasuredCalls = getNumberOfBufferedCalls();
        if(numOfMeasuredCalls == maxNumberOfBufferedCalls){
            return getNumberOfFailedCalls() * 100.0f / numOfMeasuredCalls;
        }else{
            return -1f;
        }
    }

    /**
     * Returns the maximum number of buffered calls.
     *
     * @return the maximum number of buffered calls
     */
    public long getMaxNumberOfBufferedCalls() {
        return maxNumberOfBufferedCalls;
    }

    @Override
    public synchronized int getNumberOfBufferedCalls() {
        return this.ringBitSet.length();
    }

    @Override
    public synchronized int getNumberOfFailedCalls() {
        return this.ringBitSet.cardinality();
    }
}
